package info.ipeanut.toffeepulltorefresh;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AndroidRuntimeException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Scroller;

/**
 * Created by chenshao on 16/12/13.
 */
public class HeaderPullLayout extends FrameLayout {

    private static int FRICTION = 2;
    private static int FRICTION_IMG = 6;

    private int SCROLLY_BEFORE_REFRESH = 80;
    private int SCROLLY_BEFORE_STOP = 200;

    public static int STATE_RESET = 0;
    public static int STATE_PULLING = 1;
    public static int STATE_PULLING_REFRESH = 2;
    public static int STATE_SCROLLING_BACK = 3;

    private RecyclerView recyclerView;

    private int currentState = STATE_RESET;

    private int img_initTop;

    private int img_scrollY = 0;

    private PullListener pullListener;

    private ImageView imageView;
    private Scroller scroller;
    private int touchSlop;
    private View contentLayout;
    private int mLastXIntercept;
    private int mLastYIntercept;

    private int mLastX = 0;
    private int mLastY = 0;
    float upScrollY = 0.0f;
    FrameLayout.LayoutParams params_img;

    public void setPullListener(PullListener pullListener) {
        this.pullListener = pullListener;
    }

    public HeaderPullLayout(Context context) {
        super(context);
        init();

    }

    public HeaderPullLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public HeaderPullLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        scroller = new Scroller(getContext(), new DecelerateInterpolator());
        touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        params_img = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        img_initTop = getContext().getResources().getDimensionPixelSize(R.dimen.img_init_top);
        SCROLLY_BEFORE_REFRESH = getContext().getResources().getDimensionPixelSize(R.dimen.distance_refresh);
        SCROLLY_BEFORE_STOP = getContext().getResources().getDimensionPixelSize(R.dimen.distance_stop);

    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        if (getChildCount() != 1) {
            throw new AndroidRuntimeException("HeaderPullLayout: only one child needed");
        }
        imageView = new ImageView(getContext());
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageView.setImageResource(R.drawable.ttttt);
        contentLayout = getChildAt(0);
        ViewGroup.LayoutParams params1 = contentLayout.getLayoutParams();

        removeView(contentLayout);
        addView(imageView, params_img);
        addView(contentLayout, params1);

        recyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
        if (null != recyclerView){

            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                }
            });
        }

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        imageView.layout(left, -img_initTop, right, -img_initTop + imageView.getMeasuredHeight());
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercepted = false;
                break;
            case MotionEvent.ACTION_MOVE:
                int dx = x - mLastXIntercept;
                int dy = y - mLastYIntercept;
                if (Math.abs(dy) > touchSlop
                        && Math.abs(dy) > Math.abs(dx)
                        && dy > 0
                        ) {
                    intercepted = true;
                }
                break;
        }

        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                int dy = y - mLastY;
                int dx = x - mLastX;

                if (Math.abs(dy) > Math.abs(dx)
                        && dy > 0
                        ) {
                    pullDown(dy);

                }
                break;
            case MotionEvent.ACTION_UP:

                scrollBack();
                break;
        }

        mLastX = x;
        mLastY = y;

        return true;
    }

    private void pullDown(int yDistance) {

        img_scrollY = imageView.getScrollY();
        upScrollY = contentLayout.getScrollY();
        int yScrollBy = yDistance / FRICTION;
        int toY = (int) (Math.abs(upScrollY) + yScrollBy + 1);

        if (toY < SCROLLY_BEFORE_STOP) {

            contentLayout.scrollBy(0, -yScrollBy);
            imageView.scrollBy(0, -yDistance / FRICTION_IMG);

            if (Math.abs(upScrollY) > SCROLLY_BEFORE_REFRESH) {
                currentState = STATE_PULLING_REFRESH;
            } else {
                currentState = STATE_PULLING;
            }

            if (null != pullListener) {
                float fraction = Math.abs(upScrollY) / SCROLLY_BEFORE_STOP;
                int curScrollY = (int) Math.abs(upScrollY);
                pullListener.onPullingDown(fraction, curScrollY);
            }

        }
    }

    private void scrollBack() {

        if (STATE_PULLING_REFRESH == currentState) {
            currentState = STATE_SCROLLING_BACK;
            if (null != pullListener) {
                pullListener.onRefresh();
            }
        }

        scroller.startScroll(0, (int) upScrollY, 0, (int) -upScrollY, 600);
        invalidate();

    }


    @Override
    public void computeScroll() {

        if (scroller.computeScrollOffset()) {
            int scrollY = scroller.getCurrY();
            contentLayout.scrollTo(0, scrollY);

            if (scrollY == 0) {
                scroller.abortAnimation();
                imageView.scrollTo(0, 0);
                currentState = STATE_RESET;

            } else {

                float fraction = (Math.abs(scrollY) / Math.abs(upScrollY));

                Log.d("computeScroll", scrollY + "---" + fraction + "---" + upScrollY + "---" + img_scrollY + "---"+ recyclerView.getScrollY() + "---");
                int curTop = (int) (fraction * img_scrollY);
                imageView.scrollTo(0, curTop);

                if (null != pullListener) {
                    pullListener.onScrollBack(1 - fraction, Math.abs(scrollY));
                }

            }

            postInvalidate();
        }

    }


}
